import 'package:ddwidget/mixin/dd_controller_mixin.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
// import 'dart:io' if (dart.library.html) 'dart:html';
import 'package:ddwidget/dd_widget_common.dart';

/// 下拉刷新时的状态
enum DDRefreshStatus {
  refreshing, // 刷新中
  completed, // 刷新完成
  failed, // 刷新失败
  noData, // 下拉刷新返回空数据，展示空页面
}

/// 加载数据状态
enum DDLoadStatus {
  loading, // 加载中
  noMore, // 没有更多数据了
  failed, // 加载失败
  completed // 加载完成
}

enum DDListStatus {
  waitting, // 等待中
  empty, // 空页面
  errow, // 错误页面
  normal, // 正常列表数据
}

/// 可上拉下拉刷新的列表控件，包含[分页],[空数据处理]
class DDListView extends StatefulWidget {
  final bool showScrollBar;
  final int initialPageIndex;
  final int pageSize;
  final bool showRefreshHeader;
  final bool showRefreshFooter;
  final Future<DDRefreshStatus> Function()? onRefresh;
  final Future<DDLoadStatus> Function(int pageIndex)? onLoad;
  final Widget? child;
  final Widget? emptyChild; // 空视图
  final Widget? waitingChild; // 等待视图
  final Widget? errorChild; // 错误视图
  final Widget? refreshHeader; // TODO: 自定义刷新头的逻辑还么有实现
  final Widget? refreshFooter; // TODO: 自定义加载的逻辑还木有实现
  final DDRefreshController? controller;
  final ScrollController? scrollController;
  final Axis scrollDirection;
  const DDListView({
    Key? key,
    this.initialPageIndex = 0,
    this.pageSize = 15,
    this.onRefresh,
    this.onLoad,
    this.child,
    this.showRefreshHeader = true,
    this.showRefreshFooter = true,
    this.emptyChild,
    this.refreshHeader,
    this.refreshFooter,
    this.showScrollBar = true,
    this.waitingChild,
    this.errorChild,
    this.controller,
    this.scrollDirection = Axis.vertical,
    this.scrollController,
  }) : super(key: key);
  @override
  DDListViewState createState() => DDListViewState();

  /// 能获取当前状态的目的是为了手动调用刷新,子widget可以通过context获取当前state.来手动触发刷新。
  static DDListViewState? of(BuildContext context) {
    if (context is StatefulElement && context.state is DDListViewState) {
      return context.state as DDListViewState;
    }
    DDListViewState? state = context.findAncestorStateOfType<DDListViewState>();
    return state;
  }
}

class DDListViewState extends State<DDListView> {
  final RefreshController _refreshController = RefreshController(initialRefresh: false);
  DDRefreshController? _controller;
  int _pageIndex = 0; // 内部状态
  DDListStatus _listStatus = DDListStatus.waitting;
  Future<DDRefreshStatus>? _getData; // 缓存widget.onRefresh 的Future结果，目的是为了防止FutureBuilder 一直触发。
  bool _showLoader = false; // 第一次加载的时候，不需要展示底部loadder

  @override
  void dispose() {
    _refreshController.dispose();
    _controller?.dispose();
    super.dispose();
  }

  @override
  void initState() {
    _pageIndex = widget.initialPageIndex;
    _addController();
    super.initState();
  }

  void _addController() {
    _controller = widget.controller ?? DDRefreshController();
    _controller?.addListener("refresh", (pars) {
      requestRefresh(
        needMove: pars["needMove"],
        duration: pars["duration"],
        curve: pars['curve'],
      );
    });
    _controller?.addListener("loadMore", (pars) {
      requestLoading(
        needMove: pars["needMove"],
        duration: pars["duration"],
        curve: pars['curve'],
      );
    });
  }

  /// 请求刷新
  void requestRefresh({
    bool needMove = true,
    Duration duration = const Duration(milliseconds: 300),
    Curve curve = Curves.linear,
  }) {
    _refreshController.requestRefresh(
      needMove: needMove,
      duration: duration,
      curve: curve,
    );
  }

  /// 请求加载
  void requestLoading({
    bool needMove = true,
    Duration duration = const Duration(milliseconds: 300),
    Curve curve = Curves.linear,
  }) {
    _refreshController.requestLoading(
      needMove: needMove,
      duration: duration,
      curve: curve,
    );
  }

  void _onRefresh() async {
    _refreshController.loadComplete();
    DDRefreshStatus status = DDRefreshStatus.completed;
    if (widget.onRefresh != null) {
      status = await widget.onRefresh!();
    }
    switch (status) {
      case DDRefreshStatus.completed:
        _listStatus = DDListStatus.normal;
        _refreshController.refreshCompleted();
        _pageIndex = widget.initialPageIndex; // 下拉刷新完成后，重置pageIndex

        break;
      case DDRefreshStatus.failed:
        // 从正常页面变成错误页面，不变成只留错误页面
        if (_listStatus != DDListStatus.normal) {
          _listStatus = DDListStatus.errow;
        }
        _refreshController.refreshFailed();

        break;
      case DDRefreshStatus.refreshing:
        _listStatus = DDListStatus.waitting;
        break;
      case DDRefreshStatus.noData:
        _listStatus = DDListStatus.empty;
        _refreshController.refreshCompleted();
        break;
      default:
        ddlog("请在上层返回刷新的结果");
    }
    // setState(() {});
  }

  void _onLoad() async {
    // 结束刷新
    if (_refreshController.isRefresh) {
      _refreshController.refreshCompleted();
    }
    _pageIndex++;
    DDLoadStatus status = DDLoadStatus.completed;
    if (widget.onLoad != null) {
      status = await widget.onLoad!(_pageIndex);
    }
    switch (status) {
      case DDLoadStatus.failed:
        _refreshController.loadFailed();
        _pageIndex--;
        if (_pageIndex < widget.initialPageIndex) {
          _pageIndex = widget.initialPageIndex;
        }
        break;
      case DDLoadStatus.completed:
        _refreshController.loadComplete();
        break;
      case DDLoadStatus.noMore:
        _refreshController.loadNoData();
        break;
      case DDLoadStatus.loading:
        break;
      default:
        ddlog("请返回加载状态");
    }
  }

  Future _onFirstLoad() async {
    if (_getData != null) {
      return _getData;
    }
    _getData = widget.onRefresh!();
    return _getData;
  }

  void resetListView() {
    setState(() {
      _showLoader = false;
      _pageIndex = 0;
      _listStatus = DDListStatus.waitting;
      _getData = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _onFirstLoad(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (_listStatus != DDListStatus.normal) {
          /// 这段代码只有在调用_onFirstLoad的时候会起作用。（下拉刷新上拉加载虽然也会执行，snapshot的值为null）
          final DDRefreshStatus? status = snapshot.data;
          if (status == DDRefreshStatus.failed) {
            _listStatus = DDListStatus.errow;
          } else if (status == DDRefreshStatus.noData) {
            _listStatus = DDListStatus.empty;
          } else if (status == DDRefreshStatus.completed) {
            _showLoader = widget.showRefreshFooter;
            _listStatus = DDListStatus.normal;
          }
        }
        return getRefreser(context);
      },
    );
  }

  void getListStatsus(AsyncSnapshot snapShot) {
    final DDRefreshStatus status = snapShot.data;
    if (status is! DDRefreshStatus) {
      return;
    }
    if (status == DDRefreshStatus.failed) {
      _listStatus = DDListStatus.errow;
    } else if (status == DDRefreshStatus.noData) {
      _listStatus = DDListStatus.empty;
    } else if (status == DDRefreshStatus.completed) {
      _showLoader = widget.showRefreshFooter;
      _listStatus = DDListStatus.normal;
    }
  }

  Widget getRefreser(BuildContext context) {
    Widget? child;
    switch (_listStatus) {
      case DDListStatus.errow:
        child = widget.errorChild ?? const DDListDefaultErrorWidget();
        break;
      case DDListStatus.empty:
        child = widget.emptyChild ?? const DDListDefaultEmptyWidget();
        break;
      case DDListStatus.waitting:
        child = widget.waitingChild ?? const DDListDefaultLoaddingWidget();
        break;
      case DDListStatus.normal:
        child = widget.child;
        break;
    }
    final refreser = SmartRefresher(
      physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
      controller: _refreshController,
      scrollController: widget.scrollController,
      onRefresh: _onRefresh,
      onLoading: _onLoad,
      scrollDirection: widget.scrollDirection,
      header: widget.showRefreshHeader ? (widget.refreshHeader ?? const ClassicHeader()) : null,
      footer: _showLoader ? (widget.refreshFooter ?? const ClassicFooter()) : null,
      enablePullDown: widget.showRefreshHeader,
      enablePullUp: _showLoader,
      child: child,
    );
    if (widget.showScrollBar) {
      if (kIsWeb) {
        return Scrollbar(child: refreser);
      }

      return Theme.of(context).platform == TargetPlatform.iOS
          ? CupertinoScrollbar(child: refreser)
          : Scrollbar(child: refreser);
    }
    return refreser;
  }
}

class DDRefreshController with DDControllerMixin {
  /// 代码驱动重新下拉刷新
  void refresh({
    bool needMove = true,
    Duration duration = const Duration(milliseconds: 200),
    Curve curve = Curves.linear,
  }) {
    dispatch("refresh", {
      "needMove": needMove,
      "duration": duration,
      "curve": curve,
    });
  }

  /// 代码驱动加载更多
  void loadMore({
    bool needMove = true,
    Duration duration = const Duration(milliseconds: 200),
    Curve curve = Curves.linear,
  }) {
    dispatch("loadMore", {
      "needMove": needMove,
      "duration": duration,
      "curve": curve,
    });
  }
}

/// 默认列表空视图
class DDListDefaultEmptyWidget extends StatelessWidget {
  final Widget? child;
  const DDListDefaultEmptyWidget({Key? key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: child ??
          Image.asset(
            "images/not_found.png",
            package: "ddwidget",
          ),
    );
  }
}

/// 默认列表错误视图
class DDListDefaultErrorWidget extends StatelessWidget {
  final Widget? child;
  final Function()? onRefresh;
  const DDListDefaultErrorWidget({Key? key, this.child, this.onRefresh}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: onRefresh,
        child: child ??
            Image.asset(
              "images/load_fail.png",
              package: "ddwidget",
            ),
      ),
    );
  }
}

class DDListDefaultLoaddingWidget extends StatelessWidget {
  final Widget? child;
  const DDListDefaultLoaddingWidget({Key? key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: child ??
          ((Theme.of(context).platform == TargetPlatform.iOS || Theme.of(context).platform == TargetPlatform.macOS)
              ? const CupertinoActivityIndicator()
              : const CircularProgressIndicator()),
    );
  }
}
